#include <Gal.h>
#include <stdio.h>
#include <stdlib.h>
#include <xf86drm.h>
#include <xf86drmMode.h>
#include "Private.h"
#include <string.h>

/// <summary>
/// TODO
/// </summary>
SurfacePtr NV50CreateSurface(int width, int height, int bpp)
{
	SurfacePtr surface;
	if (!(surface = (SurfacePtr)malloc(sizeof(Surface))))
		return NULL;

	surface->width = width;
	surface->height = height;
	surface->private = NULL;
	surface->refcount = 1;
	surface->stride = 0;
	surface->data = NULL;
	surface->bpp = bpp;

	return surface;
}

/// <summary>
/// TODO
/// </summary>
SurfacePtr NV50CreateWindowSurface(DriverPtr drv, int width, int height)
{
	if (width < 1 || height < 1)
		return NULL;

	SurfacePtr surface;
	if (!(surface = NV50CreateSurface(width, height, 32)))
		return NULL;

	//int f1 = NOUVEAU_BO_TILE_32BPP;
	int f2 = NOUVEAU_BO_MAP | NOUVEAU_BO_VRAM;

	struct nouveau_bo *bo;
	if (nouveau_bo_new_tile(NV_DEVICE(drv->private), f2, 0, 1000, 4, 0x7000, &bo)) {
		free(surface);
		return NULL;
	}

	surface->width = width;
	surface->height = height;
	surface->private = (void*)bo;
	surface->refcount = 1;
	surface->stride = 0;
	surface->data = NULL;
	surface->bpp = 32;

	return surface;
}

/// <summary>
/// TODO
/// </summary>
int NV50DestroySurface(SurfacePtr surface)
{
	if (surface == NULL)
		return -1;

	return 0;
}

/// <summary>
/// TODO
/// </summary>
SurfacePtr NVSurfaceFromFramebuffer(int handle, uint32_t buffer_id)
{
	drmModeFBPtr fbo;
	if ((fbo = drmModeGetFB(handle, buffer_id)) == NULL)
		return NULL;

	printf("Framebuffer:\n");	
	printf("[Depht: %d]\n", fbo->depth);
	printf("[Width: %d]\n", fbo->width);
	printf("[Height: %d]\n", fbo->height);
	printf("[Bpp: %d]\n", fbo->bpp);
	printf("[Pitch: %d]\n", fbo->pitch);

	struct nouveau_bo *bo;
	if (nouveau_bo_wrap(0, fbo->handle, &bo))
		return NULL;

	drmModeFreeFB(fbo);
	return 0;
}

/// <summary>
/// TODO
/// </summary>
void* NV50MapSurface(SurfacePtr surface)
{
	if (surface == NULL)
		return (void*)-1;

	if (surface->private == NULL)
		return (void*)-1;

	if (nouveau_bo_map(NV_BO(surface->private), NOUVEAU_BO_RDWR))
		return (void*)-1;

	return NV_BO(surface->private)->map;
}

/// <summary>
/// TODO
/// </summary>
int NV50UnmapSurface(SurfacePtr surface)
{
	if (surface == NULL)
		return -1;

	if (surface->private == NULL)
		return -1;

	nouveau_bo_unmap(NV_BO(surface->private));

	return 0;
}


